package com.gljx.util;

import com.gljx.constant.Constant;
import com.gljx.spring.SpringTool;
import com.gljx.web.Entity.Message;
import com.gljx.web.dao.MessageMapper;
import com.gljx.web.service.MessageService;
import com.gljx.web.service.impl.MessageServiceImpl;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * @Author:  LiXiang
 * @Description :
 * @Date: Created in 2018/1/25 9:31
 */

@Component
public class ActitiviUtil {




    /*@Autowired
    public void setRedisService(MessageService messageService){
        ActitiviUtil.messageService = messageService;
    }*/
/*

    @Autowired
    MessageService messageService;
*/


    MessageMapper messageService = (MessageMapper) SpringTool.getBean("messageMapper");
    //@Autowired
    //private MessageServiceImpl messageService = new MessageServiceImpl();  //添加所需service的私有成员
    /*MessageService messageService;
    private static ActitiviUtil  testUtils ;  //  关键点1   静态初使化 一个工具类  这样是为了在spring初使化之前

    private MessageService messageServiceimpl = new MessageServiceImpl();

    public void setTestService(MessageService messageService) {
        this.messageService = messageService;
    }

    @PostConstruct     //关键二   通过@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作
    public void init() {
        testUtils = this;
        testUtils.messageService = this.messageService;   // 初使化时将已静态化的testService实例化
    }*/


    /*private static MessageService messageService;

    static {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext-dao.xml");
        System.out.print("-------------------------------------------------"+ac);
        messageService = (MessageService)ac.getBean("messageService");
    }*/

    /*MessageService messageService
            =(MessageService) SpringTool.getBean("messageService");*/
    /**
     * 找不到任务
     */
    public static final String notTask = "notTask";
    /**
     * 经办人不匹配
     */
    public static final String notAssign = "notAssign";
    /**
     * 成功
     */
    public static final String SUCCESS = "success";
    /**
     * 完成
     */
    public static final String FINISH = "finish";
    /**
     * 找不到节点
     */
    public static final String notActiviti = "notActiviti";
    /**
     * 有权限
     */
    public static final String ISPOWER = "power";
    //流程引擎
    public ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    /*流程工具类*/
    public RepositoryService repositoryService = processEngine.getRepositoryService();
    public RuntimeService runtimeService = processEngine.getRuntimeService();
    public TaskService taskService = processEngine.getTaskService();
    public HistoryService historyService = processEngine.getHistoryService();

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();

        Set<String> key = map.keySet();
        for (Iterator it = key.iterator(); it.hasNext(); ) {
            String s = (String) it.next();
            System.out.println(s);
            System.out.println(map.get(s));
        }
    }

    /**
     * 开始流程并添加流程变量
     * @Author:  LiXiang
     * @Date: Created in 2018/1/25 10:17
     * @param flowKey 流程标识
     * @param map 流程变量组
     * @return String
     */
    public String creatFlow(String flowKey,Map<String,Object> map){

        /*List<Task> tasks =
                taskService
                        .createTaskQuery()
                        .processVariableValueEquals(map)
                        .list();*/

        //activiti设置认证用户（设置流程发起人）
        ProcessEngines.getDefaultProcessEngine()
                .getIdentityService()
                .setAuthenticatedUserId((String)SecurityUtils.getSubject().getPrincipal());

        ProcessInstance pi = runtimeService// 与正在执行的流程实例和执行对象相关的Service
                // 使用流程定义的key启动流程实例
                .startProcessInstanceByKey(flowKey,//流程标识
                        map);//流程变量，这是辨别流程实例的唯一方法
        return pi.getId();
    }

    /**
     * 根据流程实例ID推进流程
     * @Author:  LiXiang
     * @Date: Created in 2018/1/31 14:10
     * @param piID
     * @return
     */
    public Message completeFlowByPiID(String piID){
        Task task = taskService
                .createTaskQuery()
                .processInstanceId(piID)
                .singleResult();
        taskService.complete(task.getId());//推进任务

        Task newTask = taskService
                .createTaskQuery()
                .processInstanceId(piID)
                .singleResult();
        if(newTask != null && StringUtils.isNotEmpty(newTask.getAssignee()))
        {
            return setMessage(newTask);
        }else{
            return null;
        }

    }

    /**
     * 根据流程变量推进任务
     * @Author:  LiXiang
     * @Date: Created in 2018/1/25 10:18
     * @param VariableName 流程变量名称
     * @param Variable 流程变量
     * @return boolean
     */
    public Message complteFlowByVariable(String VariableName,Object Variable){

        Task task = taskService
                .createTaskQuery()
                .processVariableValueEquals(VariableName,Variable)//根据流程变量查询
                .singleResult();//返回唯一

        taskService.complete(task.getId());//推进任务

        //设置消息
        setMessageIsUse((String)Variable);

        Task newTask = taskService
                .createTaskQuery()
                .processVariableValueEquals(VariableName,Variable)//根据流程变量查询
                .singleResult();
        if(newTask != null && StringUtils.isNotEmpty(newTask.getAssignee()))
        {
            return setMessage(newTask);
        }else{
            return null;
        }
    }

    /**
     * 推进流程并添加流程变量
     * @Author:  LiXiang
     * @Date: Created in 2018/1/25 10:44
     * @param VariableName 流程变量名称
     * @param Variable 流程变量
     * @param map
     * @return String
     */
    public Object strictComplteFlowByVariable1(String VariableName,Object Variable,Map<String,Object> map){

        //正在进行的任务
        Task task = getTaskByVariable(VariableName,Variable);
        if(task != null )
        {
            //判断经办人
            if(!checkTaskAssignIsNowUser(task)){
                return notAssign;
            }

            //插入流程变量
            this.setVariableByTask(task,map);

            //推进任务
            taskService.complete(task.getId());

            //设置消息
            setMessageIsUse((String)Variable);

            //新的任务
            Task newTask = getTaskByVariable(VariableName,Variable);

            //寻找流程实例
            ProcessInstance rpi = getPi(task.getProcessInstanceId());
            if(rpi == null)
            {
                return FINISH;//该流程已完成
            }else{
                //如果现在的任务有经办人
                if(newTask != null && StringUtils.isNotEmpty(newTask.getAssignee()))
                {
                    return setMessage(newTask);
                }
                return SUCCESS;//操作成功
            }
        }else{
            //没有找到相关任务
            return notTask;
        }
    }

    /**
     * 推进审核流程
     * @Author:  LiXiang
     * @Date: Created in 2018/1/25 11:15
     * @param VariableName  流程变量名称
     * @param Variable
     * @param state
     * @return String
     */
    public String auditComplte(String VariableName,Object Variable,Integer state,String message){
        //正在进行的任务
        Task task = getTaskByVariable(VariableName,Variable);

        if(task != null )
        {
            //判断经办人
            if(!checkTaskAssignIsNowUser(task)){
                return notAssign;//经办人不符合
            }

            //获取正在进行的节点key
            String nowTaskKey = task.getTaskDefinitionKey();
            nowTaskKey = nowTaskKey.split("-")[0];
            String flag = nowTaskKey.split("_")[1]+"sh";

            //插入流程变量
            taskService.setVariable(task.getId(), flag, state);//0为不同意

            //添加批注
            if(StringUtils.isNotEmpty(message))
            {
                // 批注人
                Authentication.setAuthenticatedUserId((String)SecurityUtils.getSubject().getPrincipal());//批注人的名称
                taskService.addComment(task.getId() ,task.getProcessInstanceId() ,message);
            }

            //推进任务
            taskService.complete(task.getId());

            //设置消息
            setMessageIsUse((String)Variable);

            //寻找流程实例
            ProcessInstance rpi = getPi(task.getProcessInstanceId());
            if(rpi == null)
            {
                return FINISH;//该流程已完成
            }else{
                return SUCCESS;//操作成功
            }

        }else{
            return notTask;//没有找到相关任务
        }
    }

    /**
     * 推进并可能返回消息
     * @Author: LiXiang
     * @Date: Created in 2018/2/8 11:13
     * @param VariableName
     * @param Variable
     * @param state
     * @param message
     * @return
     */
    public Object auditComplteMessage(String VariableName,Object Variable,Integer state,String message){
        //正在进行的任务
        Task task = getTaskByVariable(VariableName,Variable);

        //当前账号
        String nowUser = (String)SecurityUtils.getSubject().getPrincipal();
        if(task != null )
        {
            //判断经办人
            if(!checkTaskAssignIsNowUser(task)){
                return notAssign;//经办人不符合
            }

            //获取正在进行的节点key
            String nowTaskKey = task.getTaskDefinitionKey();
            nowTaskKey = nowTaskKey.split("-")[0];
            String flag = nowTaskKey.split("_")[1]+"sh";

            //插入流程变量
            taskService.setVariable(task.getId(), flag, state);//0为不同意

            //添加批注
            if(StringUtils.isNotEmpty(message))
            {
                // 批注人
                Authentication.setAuthenticatedUserId(nowUser);//批注人的名称
                taskService.addComment(task.getId() ,task.getProcessInstanceId() ,message);
            }

            //推进任务
            taskService.complete(task.getId());

            //设置消息
            setMessageIsUse((String)Variable);

            //新的任务
            Task newTask = getTaskByVariable(VariableName,Variable);

            //寻找流程实例
            ProcessInstance rpi = getPi(task.getProcessInstanceId());
            if(rpi == null)
            {
                return FINISH;//该流程已完成
            }else{
                //如果现在的任务有经办人
                if(newTask != null && StringUtils.isNotEmpty(newTask.getAssignee()))
                {
                    return setMessage(newTask);
                }
                return SUCCESS;//操作成功
            }
        }else{
            return notTask;//没有找到相关任务
        }
    }

    /**
     * 设置消息
     * @Author:  LiXiang
     * @Date: Created in 2018/2/9 10:54
     * @param newTask
     * @return
     */
    public Message setMessage(Task newTask){
        Message resultMessage = new Message();
        //时间
        resultMessage.setCreatTime(CommonUtil.nowTimeSp("yyyy-MM-dd HH:mm"));

        //类型
        resultMessage.setType(1);//单据

        Session session = SecurityUtils.getSubject().getSession();

        //收件人
        resultMessage.setUserName(newTask.getAssignee());

        //公司和系统
        resultMessage.setCompanyid((String) session.getAttribute(Constant.CompanyId_session));
        resultMessage.setProjectid(Constant.Project_ID);

        return resultMessage;

    }

    /**
     * 根据任务设置流程变量
     * @Author:  LiXiang
     * @Date: Created in 2018/1/25 10:38
     * @param task 任务
     * @param map 流程变量组
     */
    public void setVariableByTask(Task task,Map<String,Object> map){

        //没数据结束
        if(map == null || map.size() <=0)
        {
            return;
        }
        //变量插入流程变量
        taskService.setVariables(task.getId() ,map);

    }

    /**
     * 删除正在进行的任务
     * @Author:  LiXiang
     * @Date: Created in 2018/2/7 15:34
     * @param VariableName
     * @param Variable
     * @return
     */
    public String deleteTask(String VariableName,Object Variable){


        //设置消息
        setMessageIsUse((String)Variable);

        /*runtimeService.createProcessInstanceQuery()
                .variableValueEquals(VariableName,Variable)
                .list();*/

        //查询所有历史实例
        List<HistoricProcessInstance> list =
                historyService.createHistoricProcessInstanceQuery()
                        .variableValueEquals(VariableName,Variable)
                        .list();

        if(list == null || list.size() <=0)
        {
            return notTask;//没有流程
        }else{
            //当前任务
            Task task = getTaskByVariable(
                    VariableName,
                    Variable
            );

            if(task != null)
            {
                String pid = task.getProcessInstanceId();//流程实例ID

                //删除进行的流程实例、进行的任务、进行的节点，这些信息会在历史表中更新
                runtimeService.deleteProcessInstance(pid,"");

            }


            for(int i = 0; i < list.size(); i++)
            {
                //删除历史
                historyService.deleteHistoricProcessInstance(list.get(i).getId());
            }


            return SUCCESS;
        }

    }

    /**
     * 获取以当前用户为辨别因素的流程状态
     * @Author:  LiXiang
     * @Date: Created in 2018/1/25 11:40
     * @return String
     */
    public String getTaskStateByUser(String VariableName,Object Variable){
        //直接从历史任务列表中进行查询
        List<HistoricTaskInstance> historyTaskList =
                historyService.createHistoricTaskInstanceQuery()
                        .processVariableValueEquals(VariableName,Variable)
                        .orderByHistoricTaskInstanceEndTime().desc()
                        .list();
        if(historyTaskList == null || historyTaskList.size()<= 0)
        {
            return notTask;//没有找到历史流程，即流程还未开始
        }else{
            HistoricTaskInstance hisTask = historyTaskList.get(0);
            String flowId = hisTask.getProcessInstanceId();//流程实例ID

            ProcessInstance rpi = getPi(flowId);//寻找流程实例

            if(rpi == null)
            {
                return FINISH;//查不到表示流程结束
            }else{
                //正在进行的任务
                Task task = getTaskByVariable(VariableName,Variable);
                //判断经办人
                if(!checkTaskAssignIsNowUser(task)){
                    return notAssign;//有经办人但经办人不匹配
                }
                return ISPOWER;//当前用户可以进行流程推进
            }
        }

    }

    /**
     * 为当前流程添加批注
     * @Author:  LiXiang
     * @Date: Created in 2018/1/26 16:40
     * @param VariableName
     * @param Variable
     * @return
     */
    public void setTaskMessage(String VariableName,Object Variable,String message){
        Task task = taskService
                .createTaskQuery()
                .processVariableValueEquals(VariableName,Variable)//根据流程变量查询
                .singleResult();//返回唯一
        // 批注人
        Authentication.setAuthenticatedUserId((String)SecurityUtils.getSubject().getPrincipal());//批注人的名称

        taskService.addComment(task.getId() ,task.getProcessInstanceId() ,message);
    }

    /**
     * 获取流程实例
     * @Author:  LiXiang
     * @Date: Created in 2018/1/31 14:21
     * @param flowId
     * @return
     */
    public ProcessInstance getPi(String flowId){
        ProcessInstance rpi = runtimeService
                .createProcessInstanceQuery()
                .processInstanceId(flowId)
                .singleResult();//返回唯一对象
        return rpi;
    }

    /**
     * 根据流程变量获取 “正在进行” 的任务
     * @Author:  LiXiang
     * @Date: Created in 2018/1/25 11:50
     * @param VariableName
     * @param Variable
     * @return Task
     */
    public Task getTaskByVariable(String VariableName,Object Variable){
        //按流程变量获取正在进行的任务，默认正在进行的流程流程 单据编号 不会重复
        //历史任务不会影响查询
        List<Task> task = taskService
                .createTaskQuery()
                .processVariableValueEquals(VariableName,Variable)//根据流程变量查询

                //.orderByTaskId().desc()//按创建ID倒序排序
//                .singleResult();//返回数组
                     .list();
        if(task.size()<=0){
          Task task1= taskService
                  .createTaskQuery()
                  .processVariableValueEquals(VariableName,Variable)//根据流程变量查询

                  //.orderByTaskId().desc()//按创建ID倒序排序
                .singleResult();//返回数组
//                  .list();
            task.add(task1);
        }

        return task.get(0);
    }


    public String jumpActivti(String VariableName,Object Variable,String... message){

        //当前任务
        Task task = getTaskByVariable(
                VariableName,
                Variable
        );
        if(task == null)
        {
            return notTask;
        }
        String key = task.getTaskDefinitionKey();

        if(StringUtils.isNotEmpty(key))
        {
            String[] list = key.split("-");
            if(list.length>1)
            {
                // 批注人
                Authentication.setAuthenticatedUserId((String)SecurityUtils.getSubject().getPrincipal()+"（反审核）");//批注人的名称
                if(message != null && message.length>0 && StringUtils.isNotEmpty(message[0]))
                {
                    //为任务添加批注
                    taskService.addComment(task.getId() ,task.getProcessInstanceId() ,message[0]);
                }else{
                    //为任务添加批注
                    taskService.addComment(task.getId() ,task.getProcessInstanceId() ,"反审核");
                }
                new ActivitiJump(
                        processEngine,
                        task
                ).turnTransition(list[1],null);


                //设置消息
                setMessageIsUse((String)Variable);

                return SUCCESS;//成功
            }
        }

        return notActiviti;//找不到流程节点

    }

    /**
     * 跳转节点
     * @Author:  LiXiang
     * @Date: Created in 2018/1/31 16:02
     * @param VariableName
     * @param Variable
     * @return
     */
    public Object jumpActivtiMessage(String VariableName,Object Variable,String message,Map<String,Object>... map){

        //当前任务
        Task task = getTaskByVariable(
                VariableName,
                Variable
        );
        if(task == null)
        {
            return notTask;
        }
        String key = task.getTaskDefinitionKey();

        if(StringUtils.isNotEmpty(key))
        {
            String[] list = key.split("-");
            if(list.length>1)
            {
                // 批注人
                Authentication.setAuthenticatedUserId((String)SecurityUtils.getSubject().getPrincipal()+"（反审核）");//批注人的名称
                if( StringUtils.isNotEmpty(message))
                {
                    //为任务添加批注
                    taskService.addComment(task.getId() ,task.getProcessInstanceId() ,message);
                }else{
                    //为任务添加批注
                    taskService.addComment(task.getId() ,task.getProcessInstanceId() ,"反审核");
                }
                if(map.length>0 && map[0].size()>0)
                {
                    new ActivitiJump(
                            processEngine,
                            task
                    ).turnTransition(list[1],map[0]);
                }else{
                    new ActivitiJump(
                            processEngine,
                            task
                    ).turnTransition(list[1],null);
                }

                //设置消息
                setMessageIsUse((String)Variable);

                //消息
                Message message1 = setMessage(task);

                List<HistoricProcessInstance> hist = historyService.createHistoricProcessInstanceQuery()
                        .processInstanceId(task.getProcessInstanceId())
                        .orderByProcessInstanceEndTime().desc()
                        .list();

                message1.setUserName(hist.get(0).getStartUserId());//发起人

                return message1;//成功
            }
        }

        return notActiviti;//找不到流程节点

    }




    /**
     * 直接反审核的方法
     * @param VariableName
     * @param Variable
     * @return
     */
    public Message getMessage(String VariableName,Object Variable){

        //当前任务
        Task task = getTaskByVariable(
                VariableName,
                Variable
        );
        if(task == null)
        {
            return null;
        }else{
            //消息
            Message message1 = setMessage(task);

            HistoricProcessInstance hist = historyService
                    .createHistoricProcessInstanceQuery()
                    .processInstanceId(task.getProcessInstanceId())
                    .singleResult();

            message1.setUserName(hist.getStartUserId());

            return message1;//成功
        }
    }

    /**
     * 判断当前用户是否可对任务进行推进
     * @Author:  LiXiang
     * @Date: Created in 2018/1/25 11:52
     * @param task
     * @return boolean
     */
    public boolean checkTaskAssignIsNowUser(Task task){
        //判断经办人
        String assignUser = task.getAssignee();

        //经办人存在时判断当前用户是否为经办人
        if(StringUtils.isNotEmpty(assignUser))
        {
            //当前用户
            String nowUser = (String) SecurityUtils.getSubject().getPrincipal();

            if(assignUser.contains(",")){
                String [] assignessAry = assignUser.split(",");
                if(assignessAry != null && assignessAry.length > 0){
                    for (String userName : assignessAry){
                        if(nowUser.equals(userName)){
                           return true;
                        }
                    }
                }
            }
            //匹配经办人
            if(!assignUser.equals(nowUser))
            {
                return false;
            }
        }
        return true;
    }

    /**
     * 获取当前任务节点
     * @param VariableName
     * @param Variable
     */
    public HistoricTaskInstance getNowTaskHis(String VariableName,Object Variable){
        //直接从历史任务列表中进行查询
        List<HistoricTaskInstance> historyTaskList =
                historyService.createHistoricTaskInstanceQuery()
                        .processVariableValueEquals(VariableName,Variable)
                        .orderByHistoricTaskInstanceEndTime().desc()
                        .list();

        if(historyTaskList != null && historyTaskList.size()>0)
        {
            return historyTaskList.get(0);
        }else{
            return null;
        }
    }

    /**
     * 获取当前用户于当前系统的进行中任务
     * @return
     */
    public List<Task> getNowUserFlow(){

        //当前用户
        String nowUser = (String) SecurityUtils.getSubject().getPrincipal();

        List<Task> list = processEngine.getTaskService()
                .createTaskQuery()
                .taskAssignee(nowUser)//指定个人任务查询
                .list();
        //当前项目的任务
        List<Task> drivingTask = new ArrayList<Task>();
        for (Task task :list){
            if(task.getTaskDefinitionKey().indexOf(Constant.Project_ID)>0)//该任务是否为当前系统
            {
                drivingTask.add(task);
            }
        }
        return drivingTask;
    }

    /**
     * 当前用户所有任务
     * @return
     */
    public List<HistoricTaskInstance> getNowUserHisFlow(){
        //当前用户
        String nowUser = (String) SecurityUtils.getSubject().getPrincipal();

        List<HistoricTaskInstance> list = historyService
                .createHistoricTaskInstanceQuery()
                .taskAssignee(nowUser)//指定个人任务查询
                .list();
        //当前项目的任务
        List<HistoricTaskInstance> drivingTask = new ArrayList<HistoricTaskInstance>();
        for (HistoricTaskInstance task :list){
            if(task.getTaskDefinitionKey().indexOf(Constant.Project_ID)>0)//该任务是否为当前系统
            {
                drivingTask.add(task);
            }
        }
        return drivingTask;
    }

    /**
     * 获取流程实例
     * @return
     */
    public ProcessInstance getProcessInstance(String id){
        return runtimeService
                .createProcessInstanceQuery()
                .processInstanceId(id)
                .singleResult();//返回唯一对象
    }

    /*
    设置待办事项为
     */
    public void setMessageIsUse(String fnumber){

        messageService.isUseAudit((String)SecurityUtils.getSubject().
                                            getSession().getAttribute(Constant.CompanyId_session),
                                    fnumber,
                                    1,
                                    Constant.Project_ID);
    }

}
